import re
import logging

from functools import update_wrapper

from google.appengine.ext import db

from glog.lib.decorator import decorator

import Error
from glog.base import RequestHandler
from glog.base import Role
from glog.models import Blog

@decorator
def transactionmethod(func, *args, **argkws):
    """A decorator which make the orginal method's
    datastore access in a transaction.
    """
    return db.run_in_transaction(func, *args, **argkws)


def needRole(*rolesneed):
    """Decorate a RequestHandler(or its sub-class)'s method.
    """
    def _dcrtrwrap(f):
        def _wrap(*args, **argkws):
            blogid = None
            if args:
                self = args[0]
                if hasattr(self, 'blogid'):
                    blogid = self.blogid
            roles = Role.getCurRole(blogid)
            for role in rolesneed:
                if not role in roles:
                    raise Error.NoPrivilegeError(role)
            return f(*args, **argkws)
        return update_wrapper(_wrap, f)
    return _dcrtrwrap

def blogRequest(blogid_re):
    """This decorator add blogid info to request for blog request
        The function decorated must be a instance method of
        subclass of RequestHandler.RequestHandler, which have
        reqpath attribute.
        
    """
    def _dcrtrwrap(f):
        def _wrap(*args, **argkws):
            self = None
            if args:
                self = args[0]
            if not self \
               or not hasattr(self, '__class__') \
               or not issubclass(self.__class__, RequestHandler.RequestHandler):
                raise Exception('Wrong decorate %s using blogRequest.' % func.__name__)

            m = blogid_re.match(self.reqpath)
            if m:
                blogid = m.group('blogid')
                blog = Blog.get_blog(blogid)
                if blog:
                    self.blogpath = m.group('blogpath')
                    self.blogid = blogid
                    self.blog = blog
                    self.theme = self.blog.theme
                    self.is_blogowner = Blog.is_current_user_blogowner(blogid)
                    # widgets
                    Blog.attachWidgets(self.templatedic, self.blog.widgets)
                    
                    self.templatedic['blogid'] = self.blogid
                    self.templatedic['blog'] = self.blog
                    self.templatedic['theme'] = self.theme
                    self.templatedic['is_blogowner'] = self.is_blogowner
                else:
                    raise Error.PageNotFoundError()
            else:
                raise Error.PageNotFoundError()
            return f(*args, **argkws)
        return update_wrapper(_wrap, f)
    return _dcrtrwrap
